package myJs.myPkg.reactHookForm

import myJs.Implicits.{FieldValue, JDJAn}
import myJs.myPkg.RSelect.SelectOption
import myJs.myPkg.reactHookForm.ReactHookForm.ValidateR
import org.scalajs.dom.{Event, html}
import shared.pojo.Pojo.FieldValueT
import shared.pojo.Sample.{CommentData, ProcessData, SampleInfo}
import shared.pojo.Test.TestInfoData
import slinky.core.annotations.react
import slinky.core.{ExternalComponent, SyntheticEvent, TagElement, TagMod}
import slinky.core.facade.{React, ReactElement, ReactRef}
import slinky.readwrite.ObjectOrWritten
import typings.react.mod.BaseSyntheticEvent

import scala.scalajs.js
import scala.scalajs.js.annotation.JSImport
import scala.scalajs.js.|
import scala.concurrent.Future

/**
 * Created by yz on 14/10/2022
 */
case class UseFormOptions(
                           mode: String = "onSubmit",
                           reValidateMode: String = "onChange",
                         )

case class UseFieldArrayOptions(
                                 control: Control,
                                 name: String
                               )

@JSImport("react-hook-form", JSImport.Default)
@js.native
object ReactHookForm extends js.Object {

  type ValidateR = Boolean | String

  def useForm(options: ObjectOrWritten[UseFormOptions]): UseFormRT = js.native

  def useFieldArray(options: ObjectOrWritten[UseFieldArrayOptions]): UseFieldArrayRT = js.native

}

@js.native
trait UseFormRT extends js.Object {

  type SubmitHandler = js.Function1[js.Dictionary[js.Any], js.Any]

  def register(name: String): RegisterRT = js.native

  def register(name: String, options: ObjectOrWritten[RegisterOptions]): RegisterRT = js.native

  def formState: FormStateRT = js.native

  def handleSubmit(onValid: SubmitHandler): js.Function1[SyntheticEvent[TagElement#RefType, Event], Unit] = js.native

  def watch(name: String): FieldValue = js.native

  def setValue(name: String, value: js.UndefOr[String | SelectOption]): Unit = js.native

  def trigger(name: String): Unit = js.native

  def trigger(): Unit = js.native

  def control: Control = js.native

  def reset[T](options: ObjectOrWritten[T]): Unit = js.native

}

@js.native
trait CommentDataT extends js.Object {

  val id: String = js.native

}

@js.native
trait UseFieldArrayRT extends js.Object {

  def fields: js.Array[CommentDataT] = js.native

  def append(data: ObjectOrWritten[FieldValueT]): Unit = js.native

  def insert(curI: Int, data: ObjectOrWritten[ProcessData]): Unit = js.native

  def remove(curI: Int): Unit = js.native

}

@js.native
trait ErrorField extends js.Object {

  val message: js.UndefOr[String] = js.native

  val `type`: js.UndefOr[String] = js.native

}

@js.native
trait FormStateRT extends js.Object {

  def errors: js.Dictionary[ErrorField] = js.native

}

@js.native
trait RegisterRT extends js.Object {

  type ChangeHandler = SyntheticEvent[TagElement#RefType, Event] => Unit

  def name: String = js.native

  def onChange: js.Function1[SyntheticEvent[TagElement#RefType, Event], Unit] = js.native

  def ref: ReactRef[html.Input] = js.native

  def onBlur: ChangeHandler = js.native

}

case class ValidationValueMessage(
                                   value: js.UndefOr[Boolean | js.RegExp | Int] = js.undefined,
                                   message: js.UndefOr[String] = js.undefined,
                                 )


case class RegisterOptions(
                            required: js.UndefOr[ValidationValueMessage] = js.undefined,
                            valueAsNumber: js.UndefOr[Boolean] = js.undefined,
                            pattern: js.UndefOr[ValidationValueMessage] = js.undefined,
                            min: js.UndefOr[ValidationValueMessage] = js.undefined,
                            max: js.UndefOr[ValidationValueMessage] = js.undefined,
                            validate: js.UndefOr[String => ValidateR | Future[ValidateR]] = js.undefined,
                          )

@js.native
trait Control extends js.Object {

}

@js.native
trait FieldT extends js.Object {

  type ChangeHandler = SyntheticEvent[TagElement#RefType, Event] => Unit

  def name: String = js.native

  def value: FieldValue = js.native

  def onChange: js.Function1[SyntheticEvent[TagElement#RefType, Event], Unit] = js.native

  def ref: ReactRef[html.Select] = js.native

  def onBlur: ChangeHandler = js.native

}

case class FieldOptions(
                         name: js.UndefOr[String],
                         ref: ReactRef[html.Input],
                         value: js.UndefOr[String],
                         onChange: SyntheticEvent[TagElement#RefType, Event] => Unit
                       )

@js.native
trait FieldR extends js.Object {

  def field: FieldT = js.native

}

@react object Controller extends ExternalComponent {
  case class Props(
                    name: js.UndefOr[String] = js.undefined,
                    control: js.UndefOr[Control] = js.undefined,
                    render: js.UndefOr[FieldR => ReactElement] = js.undefined,
                    rules: js.UndefOr[RegisterOptions] = js.undefined,
                    defaultValue: js.UndefOr[String | SelectOption] = js.undefined,
                    dialogClassName: js.UndefOr[String] = js.undefined,
                  )

  @js.native
  @JSImport("react-hook-form", "Controller")
  object Component extends js.Object {

  }

  override val component = Component


}
